package com.lagou.edu.factory;

import com.lagou.edu.anno.AutoWired;
import com.lagou.edu.anno.Service;
import com.lagou.edu.anno.Transactional;
import org.reflections.Reflections;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;

/**
 * 对象工厂类（使用反射技术，解析自定义注解，实现依赖注入和bean的实例化）
 */
public class BeanFactoryByAnno {

    private static Map<String, Object> map = new HashMap<>();

    static{
        // 扫描@Service注解类，获取反射对象集合
        Reflections reflections = new Reflections("com.lagou.edu");
        Set<Class<?>> annotatedWith = reflections.getTypesAnnotatedWith(Service.class);
        annotatedWith.forEach(o ->{
            try {
                // 实例对象
                Object bean = o.newInstance();
                Class<?> aClass = bean.getClass();
                Service annotation = aClass.getAnnotation(Service.class);
                // 判断是否给定value值
                if (annotation != null && StringUtils.isEmpty(annotation.value())) {
                    String[] serviceSplit = o.getName().split("\\.");
                    map.put(serviceSplit[serviceSplit.length - 1], bean);

                } else {
                    map.put(annotation.value(), bean);
                }

            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }

        });
        // 实例化完成后维护对象之间的依赖关系
        Set<Map.Entry<String, Object>> entries = map.entrySet();
        entries.forEach(entry -> {
            // 获取使用注解Service的类
            Object value = entry.getValue();
            Class<?> valueClass = value.getClass();
            // 使用反射获取类的所有字段
            List<Field> fields = Arrays.asList(valueClass.getDeclaredFields());
            Object finalValue = value;
            fields.forEach(field -> {
                // 判断字段上是否含有AutoWrize注解
                if (field.isAnnotationPresent(AutoWired.class)) {
                    String[] typeSplit = field.getType().getName().split("\\.");
                    String name = typeSplit[typeSplit.length - 1];
                    // 拿到反射对象的所有方法
                    List<Method> methods = Arrays.asList(valueClass.getMethods());
                    methods.forEach(method -> {
                        // 判断是否存在set+name方法
                        if (method.getName().equalsIgnoreCase("set" + name)) {
                            try {
                                // 对该方法进行依赖关系的处理
                                method.invoke(finalValue, map.get(name));
                            } catch (IllegalAccessException e) {
                                e.printStackTrace();
                            } catch (InvocationTargetException e) {
                                e.printStackTrace();
                            }
                        }
                    });
                }
            });
            // 判断该方法是否持有Transactional注解
            if (valueClass.isAnnotationPresent(Transactional.class)) {
                ProxyFactory proxyFactory = (ProxyFactory) BeanFactoryByAnno.getBean("proxyFactory");
                Class<?>[] isInterfaces = valueClass.getInterfaces();
                // 提供了接口的使用jdk动态代码，否则使用cglib动态代理模式
                if (isInterfaces != null && isInterfaces.length > 0) {
                    value = proxyFactory.getJdkProxy(value);
                } else {
                    value = proxyFactory.getCglibProxy(value);
                }
            }
            map.put(entry.getKey(), value);
        });
    }
    // 提供获取实例对象接口
    public static Object getBean(String id) {
        return map.get(id);
    }
}
